NHN GPU 서버 PyTorch 실습 가이드
1. 환경 설정
서버 생성 사양
- OS: Ubuntu Server 22.04.5 LTS with NVIDIA (2025.07.15)
- 사양: g2.t4.c4m32 (제일 낮은 사양)
- 보안 정책: 22번, 8000번 포트만 오픈
서버 접속
ssh -i <your-key.pem> ubuntu@<GPU_SERVER_IP>
<your-key.pem>: 서버 생성 시 받은 키파일
<GPU_SERVER_IP>: NHN 콘솔에서 확인 가능한 서버 IP
기본 시스템 준비
시스템 업데이트
sudo apt update
최소화된 업데이트만 실행하여 시간 절약
Python 환경 확인
python3 --version
pip3 --version
필요시 Python 설치
sudo apt install -y python3-venv python3-pip
작업 디렉토리 및 가상환경 생성
cd ~
mkdir ai-project && cd ai-project
python3 -m venv venv
source venv/bin/activate
이후 모든 작업은
(venv)표시된 상태에서 진행
가상환경이 정상 활성화되었는지 확인
- 터미널 프롬프트 앞에
(venv)표시 확인 which python으로 가상환경의 Python이 선택되었는지 확인
2. PyTorch 설치
GPU 지원 PyTorch 설치
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
설치 과정 설명
torch: PyTorch 코어 라이브러리torchvision: 컴퓨터 비전용 데이터셋과 변환 도구torchaudio: 오디오 처리용 (이번 실습에서는 미사용)--index-url: CUDA 12.1 지원 버전 설치를 위한 PyTorch 전용 저장소
GPU 인식 확인
python -c "import torch; print(torch.cuda.is_available())"
예상 결과: True
False가 나올 경우 GPU 드라이버나 CUDA 설정 문제
추가 GPU 정보 확인
# GPU 정보 확인용 스크립트 생성
cat > gpu_info.py << 'EOF'
import torch
print(f'CUDA 버전: {torch.version.cuda}')
print(f'GPU 개수: {torch.cuda.device_count()}')
if torch.cuda.is_available():
print(f'GPU 이름: {torch.cuda.get_device_name(0)}')
else:
print('GPU 없음')
EOF
# 실행
python gpu_info.py
3. MNIST 학습 실습
학습 코드 작성
cd ~/ai-project
nano train.py
train.py 코드 입력
import torch, torch.nn as nn, torch.optim as optim
import torchvision, torchvision.transforms as transforms
# 1) 데이터셋
train = torchvision.datasets.MNIST(
root='./data', train=True, transform=transforms.ToTensor(), download=True
)
trainloader = torch.utils.data.DataLoader(train, batch_size=64, shuffle=True)
# 2) 모델 정의
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1, self.fc2 = nn.Linear(28*28, 128), nn.Linear(128, 10)
def forward(self, x):
x = x.view(-1, 28*28)
return self.fc2(torch.relu(self.fc1(x)))
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
net = Net().to(device)
# 3) 학습 설정
opt = optim.Adam(net.parameters())
loss_fn = nn.CrossEntropyLoss()
# 4) 학습 (1 Epoch만)
for epoch in range(1):
for imgs, labels in trainloader:
imgs, labels = imgs.to(device), labels.to(device)
opt.zero_grad()
loss = loss_fn(net(imgs), labels)
loss.backward()
opt.step()
print(f"Epoch {epoch+1}, Loss: {loss.item()}")
# 5) 모델 저장
torch.save(net.state_dict(), "mnist_model.pth")
print("✅ 학습 완료, mnist_model.pth 저장됨")
코드 구성 요소 설명
1. 데이터셋 준비
MNIST: 0~9 손글씨 숫자 이미지 데이터셋 (28x28 픽셀)transforms.ToTensor(): PIL 이미지를 PyTorch 텐서로 변환batch_size=64: 한 번에 64개 이미지씩 처리shuffle=True: 학습 데이터를 무작위로 섞어서 사용
2. 신경망 모델
Linear(28*28, 128): 입력층 → 은닉층 (784 → 128)Linear(128, 10): 은닉층 → 출력층 (128 → 10개 클래스)ReLU: 활성화 함수 (음수를 0으로 변환)view(-1, 28*28): 2D 이미지를 1D 벡터로 평탄화
3. 학습 설정
Adam: 적응적 학습률을 사용하는 최적화 알고리즘CrossEntropyLoss: 다중 클래스 분류용 손실 함수
학습 실행
python train.py
실행 과정 설명
- MNIST 데이터셋 다운로드 (최초 실행시만)
- 학습 진행 (약 1분 소요)
mnist_model.pth파일 생성
예상 출력
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
...
Epoch 1, Loss: 0.3161914646625519
✅ 학습 완료, mnist_model.pth 저장됨
HTTP 404 에러가 발생해도 백업 서버에서 자동 다운로드되므로 정상
4. 모델 추론
추론 코드 작성
nano infer.py
infer.py 코드 입력
import torch, torch.nn as nn
import torchvision, torchvision.transforms as transforms
# 모델 구조 (train.py와 동일해야 함)
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1, self.fc2 = nn.Linear(28*28, 128), nn.Linear(128, 10)
def forward(self, x):
x = x.view(-1, 28*28)
return self.fc2(torch.relu(self.fc1(x)))
# 모델 로드
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
net = Net().to(device)
net.load_state_dict(torch.load("mnist_model.pth", map_location=device))
net.eval()
# 테스트 데이터
testset = torchvision.datasets.MNIST(
root='./data', train=False, download=True, transform=transforms.ToTensor()
)
img, label = testset[0]
# 추론
with torch.no_grad():
output = net(img.view(1,1,28,28).to(device))
pred = output.argmax(1).item()
print("실제 정답:", label)
print("모델 예측:", pred)
추론 코드 핵심 개념
모델 로딩
load_state_dict(): 저장된 가중치를 모델에 로드map_location=device: CPU/GPU 호환성 보장net.eval(): 평가 모드로 전환 (드롭아웃, 배치정규화 비활성화)
추론 과정
torch.no_grad(): 그래디언트 계산 비활성화로 메모리 절약argmax(1): 가장 높은 확률의 클래스 인덱스 반환item(): 텐서에서 파이썬 숫자값 추출
추론 실행
python infer.py
예상 출력
실제 정답: 7
모델 예측: 7
5. API 서버 구축
FastAPI 설치
pip install fastapi uvicorn
API 서버 코드 작성
nano app.py
app.py 코드 입력
from fastapi import FastAPI
from fastapi.responses import JSONResponse
import torch, torch.nn as nn
app = FastAPI()
# 모델 정의 (train.py와 동일)
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1, self.fc2 = nn.Linear(28*28, 128), nn.Linear(128, 10)
def forward(self, x):
x = x.view(-1, 28*28)
return self.fc2(torch.relu(self.fc1(x)))
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
net = Net().to(device)
net.load_state_dict(torch.load("mnist_model.pth", map_location=device))
net.eval()
@app.get("/predict/{digit}")
def predict(digit: int):
result = {"입력": digit, "예측": (digit+1) % 10}
return JSONResponse(content=result, media_type="application/json; charset=utf-8")
FastAPI 핵심 개념
웹 프레임워크 설정
FastAPI(): 고성능 비동기 웹 프레임워크@app.get(): HTTP GET 요청 라우터JSONResponse: JSON 형태로 응답 반환
서버 실행
uvicorn app:app --host 0.0.0.0 --port 8000
실행 옵션 설명
app:app:app.py파일의app객체 실행--host 0.0.0.0: 모든 네트워크 인터페이스에서 접근 허용--port 8000: 8000번 포트 사용
API 테스트
로컬에서 테스트
curl http://localhost:8000/predict/5
외부에서 테스트
curl http://<GPU_SERVER_IP>:8000/predict/5
예상 응답
{"입력":5,"예측":6}
브라우저에서 확인
http://<GPU_SERVER_IP>:8000/docs: 자동 생성된 API 문서http://<GPU_SERVER_IP>:8000/predict/3: 직접 API 호출
6. 트러블슈팅
자주 발생하는 문제들
1. GPU 인식 불가
# GPU 상태 확인
nvidia-smi
# PyTorch에서 CUDA 버전 확인
python -c "import torch; print(torch.version.cuda)"
해결방법: 서버 재시작 또는 드라이버 재설치
참고:
nvcc --version명령어는 CUDA 컴파일러가 별도 설치되어야 사용 가능하며, PyTorch 사용에는 필수가 아닙니다.
2. 가상환경 비활성화
# 가상환경 재활성화
source ~/ai-project/venv/bin/activate
3. 메모리 부족 에러
# GPU 메모리 확인
nvidia-smi
# 배치 사이즈 줄이기 (train.py에서)
# batch_size=64 → batch_size=32
4. 포트 접근 불가
- NHN 클라우드 보안 그룹에서 8000번 포트 추가
- 방화벽 설정 확인
5. 패키지 설치 실패
# pip 업그레이드
pip install --upgrade pip
# 캐시 삭제 후 재설치
pip cache purge
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121